//---------------------------------------------------------------------------------
#include <QtDebug>
#include <QKeyEvent>
#include <QMessageBox>
#include "CMainWindow.h"
#include "CMapReader.h"
//---------------------------------------------------------------------------------
#define TIMER	100
//---------------------------------------------------------------------------------
CMainWindow::CMainWindow(int curLevel) : QMainWindow() {
	setupUi(this);
	
	this->curLevel=curLevel;
	nbVie=1000;
	MPFunctions[CMap::eaMoveUp]=&CMainWindow::moveUp;
	MPFunctions[CMap::eaMoveDown]=&CMainWindow::moveDown;
	MPFunctions[CMap::eaMoveRight]=&CMainWindow::moveRight;
	MPFunctions[CMap::eaMoveLeft]=&CMainWindow::moveLeft;
	MPFunctions[CMap::eaPushUp]=&CMainWindow::pushUp;
	MPFunctions[CMap::eaPushDown]=&CMainWindow::pushDown;
	MPFunctions[CMap::eaPushRight]=&CMainWindow::pushRight;
	MPFunctions[CMap::eaPushLeft]=&CMainWindow::pushLeft;
	
	connect(sceneWidget, SIGNAL(restart()), this, SLOT(onRestart()));
	connect(sceneWidget, SIGNAL(win()), this, SLOT(onWin()));
	connect(sceneWidget, SIGNAL(playerMove(QList<CMap::EAction>)), this, SLOT(onPlayerMove(QList<CMap::EAction>)));
	
	timer=new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(onTimerTimeout()));
	
	map=new CMap();
	sceneWidget->setMap(map);
	loadLevel();
	
	timer->start(TIMER);
}
//---------------------------------------------------------------------------------
void CMainWindow::updateAffichage(void) {
	levelInfoLbl->setText(tr("Niveau")+" "+QString::number(curLevel));
	nbVieLbl->setText("x "+QString::number(nbVie));
	scoreLbl->setText(	tr("Déplacement")+" : "+
						QString::number(nbDeplacement)+" "+
						tr("Déplacement de caisse")+" : "+QString::number(nbPush));
}
//---------------------------------------------------------------------------------
void CMainWindow::loadLevel(void) {
	map->clean();
	map->load(qApp->applicationDirPath()+"/levels/level"+QString::number(curLevel).rightJustified(4, QChar('0'))+".xsb");
	nbDeplacement=nbPush=0;
	sceneWidget->reset();
	
	pbPrev->setEnabled(curLevel > 0);
}
//---------------------------------------------------------------------------------
void CMainWindow::moveUp(void) {
	nbDeplacement++;
	map->moveUp();
}
//---------------------------------------------------------------------------------
void CMainWindow::moveDown(void) {
	nbDeplacement++;
	map->moveDown();
}
//---------------------------------------------------------------------------------
void CMainWindow::moveRight(void) {
	CMario::getInstance()->setSens(CMario::tsDroite);
	nbDeplacement++;
	map->moveRight();
}
//---------------------------------------------------------------------------------
void CMainWindow::moveLeft(void) {
	CMario::getInstance()->setSens(CMario::tsGauche);
	nbDeplacement++;
	map->moveLeft();
}
//---------------------------------------------------------------------------------
void CMainWindow::pushUp(void) {
	nbPush++;
	map->pushUp();
}
//---------------------------------------------------------------------------------
void CMainWindow::pushDown(void) {
	nbPush++;
	map->pushDown();
}
//---------------------------------------------------------------------------------
void CMainWindow::pushRight(void) {
	CMario::getInstance()->setSens(CMario::tsDroite);
	nbPush++;
	map->pushRight();
}
//---------------------------------------------------------------------------------
void CMainWindow::pushLeft(void) {
	CMario::getInstance()->setSens(CMario::tsGauche);
	nbPush++;
	map->pushLeft();
}
//---------------------------------------------------------------------------------
void CMainWindow::onRestart(void) {
	timer->stop();
	nbVie--;
	
	updateAffichage();
	if(nbVie == 0) {
		nbVie=1000;
		curLevel=1;
		QMessageBox::critical(this, tr("Perdu"), tr("Gros nul !"));
	}
	
	loadLevel();
	
	timer->start(TIMER);
}
//---------------------------------------------------------------------------------
void CMainWindow::onWin(void) {
	timer->stop();
	QMessageBox::information(this, tr("Félicatation"), tr("Félication, vous avez réussi ce niveau !"));
	
	curLevel++;
	
	loadLevel();
	
	timer->start(TIMER);
}
//---------------------------------------------------------------------------------
void CMainWindow::onTimerTimeout(void) {
	CMario* mario=CMario::getInstance();
	
	if(map->hasWin()) {
		onWin();
	}
	
	mario->setIsMoving(false);
	if(!nextActions.empty()) {
		CMap::EAction action=nextActions.takeFirst();
		
		mario->setIsMoving(true);
		(this->*MPFunctions[action])();
	}
	
	sceneWidget->nextStep();
	sceneWidget->update();
	updateAffichage();
}
//---------------------------------------------------------------------------------
void CMainWindow::onPlayerMove(QList<CMap::EAction> actions) {
	nextActions.append(actions);
}
//---------------------------------------------------------------------------------
void CMainWindow::on_pbRecharger_clicked(bool) {
	if(QMessageBox::question(this, tr("Question"), tr("Etes vous sûre de vouloir recharger ce niveau ?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
		loadLevel();
	}
}
//---------------------------------------------------------------------------------
void CMainWindow::on_pbPrev_clicked(bool) {
	if(QMessageBox::question(this, tr("Question"), tr("Etes vous sûre de vouloir changer de niveau ?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
		curLevel--;
		loadLevel();
	}
}
//---------------------------------------------------------------------------------
void CMainWindow::on_pbNext_clicked(bool) {
	if(QMessageBox::question(this, tr("Question"), tr("Etes vous sûre de vouloir changer de niveau ?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
		curLevel++;
		loadLevel();
	}
}
//---------------------------------------------------------------------------------